using dnAnalytics.LinearAlgebra;
using dnAnalytics.LinearAlgebra.Solvers;

namespace dnAnalytics.Examples.LinearAlgebra.Solvers.Preconditioners
{
    public sealed class DiagonalPreconditioner
    {
        /// <summary>
        /// Creates a new sparse matrix with zero values everywhere except
        /// on the diagonal where the values are equal to 1.0.
        /// </summary>
        private Matrix CreateMatrix(int size)
        {
            // Create the sparse matrix with the specified size
            Matrix matrix = MatrixBuilder.CreateMatrix(size, MatrixType.Sparse);
            // Add values to the matrix. For now we'll make the matrix
            // a unit matrix.
            for (int i = 0; i < size; i++)
            {
                matrix[i, i] = 1.0;
            }

            return matrix;
        }

        /// <summary>
        /// The main method that runs the BiCGStab iterative solver.
        /// </summary>
        public void UseSolver()
        {
            // Create a sparse matrix. For now the size will be 10 x 10 elements
            Matrix matrix = CreateMatrix(10);

            // Create the right hand side vector. The size is the same as the matrix
            // and all values will be 2.0.
            Vector rightHandSideVector = VectorBuilder.CreateVector(10, 2.0, VectorType.Dense);

            // Create the DiagonalIluFactorization preconditioner
            // We need a link to the matrix so the pre-conditioner can do it's work.
            dnAnalytics.LinearAlgebra.Solvers.Preconditioners.DiagonalPreconditioner preconditioner =
                new dnAnalytics.LinearAlgebra.Solvers.Preconditioners.DiagonalPreconditioner(matrix);

            // Create the actual preconditioner
            preconditioner.CreatePreconditioner();

            // Now that all is set we can solve the matrix equation.
            Vector solutionVector = preconditioner.Solve(rightHandSideVector);

            // Another way to get the values is by using the overloaded solve method
            // In this case the solution vector needs to be of the correct size.
            preconditioner.Solve(rightHandSideVector, solutionVector);
        }
    }
}